

from rest_framework import serializers
from goods.models import SKU,SKUSpecification,GoodsCategory,SPU
from goods.models import SPUSpecification,SpecificationOption

# 定义选项对象序列化器
class SpecOptionModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = [
            'id',
            'value'
        ]


# 定义可选规格及选项信息
class SPUSpecOptModelSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()

    # 与当前规格对象关联的多条选项对象
    options = SpecOptionModelSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = [
            'id',
            'name',
            'spu',
            'spu_id',
            'options'
        ]



# 定义序列化SPU商品序列化器
class SPUSimpleModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = [
            'id',
            'name'
        ]


# 定义分类序列化器
class GoodsCategoryModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = [
            'id',
            'name'
        ]


# 自定义序列化sku规格选项中间表数据序列化器
class SKUSpecOptModelSerializer(serializers.ModelSerializer):
    # spec_id和option_id是特殊的隐藏字段，不会自动映射
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = [
            'spec_id',
            'option_id'
        ]


class SKUDetailModelSerializer(serializers.ModelSerializer):
    # 如果自动映射的字段序列化结果不符合接口定义，需要重写覆盖
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()
    category = serializers.StringRelatedField()
    category_id = serializers.IntegerField()

    # 代表与当前主表SKU对象管理的从表SKUSpecification的多条数据
    # 序列化SKUSpecification多条数据，字段"spec_id"，"option_id"
    # 业务： 新建sku，  传入的参数specs是规格和选项信息(不属于sku固有属性，
    # 是属于中间表数据)；
    # [{spec_id: "4", option_id: 8}, {spec_id: "5", option_id: 11}]
    # read_only=True新建sku的时候，舍弃规格和选项信息
    # specs = SKUSpecOptModelSerializer(many=True, read_only=True)
    # 在我们的业务中，必须在中间表中记录sku的规格信息，所以不能舍弃
    specs = SKUSpecOptModelSerializer(many=True)

    class Meta:
        model = SKU
        fields = '__all__' # 把模型类所有字段自动映射


    # 模型类序列化器的create方法无法完成中间表数据的新建
    # 自定以该方法来做
    def create(self, validated_data):
        # 1、在有效数据中提取出规格选项信息
        # pop: 把key从字段中去除并返回
        specs = validated_data.pop('specs')
        # 2、新建sku对象
        sku = super().create(validated_data) # 使用原有的模型类序列化器的create方法完成sku对象构建
        # 3、插入中间表规格选项信息
        # specs = [{spec_id: "4", option_id: 8}, {spec_id: "5", option_id: 11}]
        for spec in specs:
            # spec = {spec_id: "4", option_id: 8}
            # spec字典中添加sku_id字段
            spec['sku_id'] = sku.id # {spec_id: "4", option_id: 8, 'sku_id': 18}
            # 创建中间表的一条数据，记录其一条规格和选项信息
            SKUSpecification.objects.create(**spec) # create(spec_id=4, option_id=8, sku_id=18)

        # 4、返回新建的sku对象
        return sku


    # 模型类序列化器地update方法无法完成中间表数据地更新
    # 自定义
    def update(self, instance, validated_data):
        # 1、提取中建表数据
        specs = validated_data.pop('specs')
        # 2、更新sku对象地固有属性
        sku = super().update(instance, validated_data)
        # 3、更新中间表数据
        # 3.1 删除原有地中间表记录地规格和选项信息
        SKUSpecification.objects.filter(sku_id=sku.id).delete()
        # 3.2 再更具前端传递地新的规格和选项信息新建中间表数据
        for spec in specs:
            spec['sku_id'] = sku.id
            SKUSpecification.objects.create(**spec)

        # 4、返回sku对象
        return sku








